#include "stdafx.h"
#include "QvRandom.h"

static QvInt32 MBIG  = 0x7FFFFFFF;
static QvInt32 MSEED = 0x9A4EC86;
static QvInt32 MZ    = 0;

QvRandom::QvRandom(void)
{
    Init(GetTickCount());
}

QvRandom::QvRandom(QvInt32 nSeed)
{
    Init(nSeed);
}

void QvRandom::Init(QvInt32 nSeed)
{
    QvInt32 num2 = MSEED - abs(nSeed);
    objSeedArray[0x37] = num2;
    QvInt32 num3 = 1;
    for (QvInt32 i = 1; i < 0x37; i++)
    {
        QvInt32 index = (0x15 * i) % 0x37;
        objSeedArray[index] = num3;
        num3 = num2 - num3;
        if (num3 < MZ)
        {
            num3 += MBIG;
        }
        num2 = objSeedArray[index];
    }
    for (QvInt32 j = 1; j < 5; j++)
    {
        for (QvInt32 k = 1; k < 0x38; k++)
        {
            objSeedArray[k] -= objSeedArray[1 + ((k + 30) % 0x37)];
            if (objSeedArray[k] < MZ)
            {
                objSeedArray[k] += MBIG;
            }
        }
    }
    m_nInext = 0;
    m_nInextp = 0x15;
    nSeed = 1;
}

QvInt32 QvRandom::NextInt()
{
    QvInt32 nInext = m_nInext;
    QvInt32 nInextp = m_nInextp;
    if (++nInext >= 0x38)
    {
        nInext = 1;
    }
    if (++nInextp >= 0x38)
    {
        nInextp = 1;
    }
    QvInt32 num = objSeedArray[nInext] - objSeedArray[nInextp];
    if (num < 0)
    {
        num += MBIG;
    }
    objSeedArray[nInext] = num;
    m_nInext = nInext;
    m_nInextp = nInextp;
    return num;
}

QvInt32 QvRandom::NextInt(QvInt32 maxValue)
{
    if (maxValue < 0)
    {
        maxValue = abs(maxValue);
    }
    return (QvInt32) (NextDouble() * maxValue);
}

QvInt32 QvRandom::NextInt(QvInt32 minValue, QvInt32 maxValue)
{
    if (minValue > maxValue)
    {
        QvInt32 n = minValue;
        minValue = maxValue;
        maxValue = n;
    }
    QvLong num = maxValue - minValue;
    if (num <= MBIG)
    {
        return (((QvInt32) (NextDouble() * num)) + minValue);
    }
    return (((QvInt32) ((QvLong) (GetSampleForLargeRange() * num))) + minValue);
}

QvDouble QvRandom::NextDouble()
{
    return (NextInt() * 4.6566128752457969E-10);
}

QvDouble QvRandom::GetSampleForLargeRange()
{
    QvInt32 num = NextInt();
    if (NextInt() & 0x1)
    {
        num = -num;
    }
    QvDouble num2 = num + 2147483646.0;
    return (num2 / 4294967293);
}


